package com.yf.exam.modules.exam.ext.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yf.ability.redis.service.RedisService;
import com.yf.base.api.api.dto.PagingReqDTO;
import com.yf.base.api.exception.ServiceException;
import com.yf.exam.enums.PaperExState;
import com.yf.exam.modules.exam.ext.dto.*;
import com.yf.exam.modules.exam.ext.service.ExamWatchService;
import com.yf.exam.modules.paper.mapper.PaperMapper;
import com.yf.exam.modules.paper.service.PaperService;
import com.yf.exam.websocket.server.ExamEndpoint;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.util.List;

@Service
public class ExamWatchServiceImpl implements ExamWatchService {


    @Autowired
    private RedisService redisService;

    @Autowired
    private PaperService paperService;

    @Autowired
    private ExamEndpoint examEndpoint;

    @Autowired
    private PaperMapper paperMapper;

    @Override
    public void sendBatchMsg(String examId, String msg) {
        try {
            examEndpoint.sendAll(examId, msg);
        } catch (IOException e) {
            e.printStackTrace();
            throw new ServiceException("消息发送失败："+e.getMessage());
        }
    }

    @Override
    public void sendSingleMsg(String examId, String userId, String msg) {
        try {
            examEndpoint.send(examId, userId, msg);
        } catch (IOException e) {
            e.printStackTrace();
            throw new ServiceException("消息发送失败："+e.getMessage());
        }
    }

    @Override
    public WatchStatRespDTO watchStat(String examId) {
        return paperMapper.selectWatchStat(examId);
    }

    @Override
    public IPage<WatchUserRespDTO> watchPaging(PagingReqDTO<WatchUserReqDTO> reqDTO) {

        WatchUserReqDTO params = reqDTO.getParams();
        if(params==null || StringUtils.isBlank(params.getExamId())){
            throw new ServiceException("考试ID必须传入！");
        }

        // 在线离线都没勾选
        if(params.getOnline()!=null && !params.getOnline() && params.getOffline()!=null && !params.getOffline()){
            return reqDTO.toPage();
        }

        // Redis在线列表
        List<String> userIds = redisService.findList(params.getExamId());

        // 只查找在线的
        if(params.getOnline()!=null && params.getOnline() && params.getOffline()!=null && !params.getOffline()){
            if(CollectionUtils.isEmpty(userIds)){
                return reqDTO.toPage();
            }
            params.setIncludes(userIds);
        }

        // 排除在线的
        if(params.getOnline()!=null && !params.getOnline() && params.getOffline()!=null && params.getOffline()){
            params.setExcludes(userIds);
        }



        IPage<WatchUserRespDTO> pageData = paperMapper.watchPaging(reqDTO.toPage(), params);

        if(CollectionUtils.isEmpty(userIds)){
            return pageData;
        }

        // 构建在线状态
        if(pageData!=null && !CollectionUtils.isEmpty(pageData.getRecords())){
            List<WatchUserRespDTO> records = pageData.getRecords();
            for(WatchUserRespDTO item: records){
                if(userIds.contains(item.getUserId())){
                    item.setOnline(true);
                }else{
                    item.setOnline(false);
                }
            }
        }

        return pageData;
    }

    @Override
    public IPage<WatchPaperRespDTO> handPaging(PagingReqDTO<WatchPaperReqDTO> reqDTO) {
        return paperMapper.handPaging(reqDTO.toPage(), reqDTO.getParams());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void forceHand(String paperId, String message) {
        paperService.handExam(paperId, PaperExState.ADMIN_FORCE, message);
    }
}
